import numpy as np
import pandas as pd


def loadDataSet():
    return [['a', 'c', 'e'], ['b', 'd'], ['b', 'c'], ['a', 'b', 'c', 'd'], ['a', 'b'], ['b', 'c'], ['a', 'b'],
            ['a', 'b', 'c', 'e'], ['a', 'b', 'c'], ['a', 'c', 'e']]


def loaddata():
    order_data = pd.read_csv('GoodsOrder.csv', header=0, encoding='gbk')

    order_data['Goods'] = order_data['Goods'].apply(lambda x: "," + x)
    order_data = order_data.groupby('id').sum().reset_index()
    order_data['Goods'] = order_data['Goods'].apply(lambda x: [x[1:]])
    order_data_list = list(order_data['Goods'])
    # print(order_data_list)
  
    data_translation = []
    for i in order_data_list:
       
        p = i[0].split(",")
        data_translation.append(p)
    return data_translation


def creatC1(data):
 
    C1 = []
    for row in dataSet:
        for item in row:
            if [item] not in C1:
                C1.append([item])

    C1.sort()
    
    return list(map(frozenset, C1))


def calSupport(D, C, minSupport):
    
    dict_sup = {}  
   
    for i in D:
        for j in C:
          
            if j.issubset(i):
                
                if j not in dict_sup:
                    dict_sup[j] = 1
                else:
                    dict_sup[j] += 1
    
    sumCount = float(len(D))
    
    supportData = {}  
    relist = []  
    for i in dict_sup:
        temp_sup = dict_sup[i] / sumCount
        if temp_sup > minSupport:
            relist.append(i)
            supportData[i] = temp_sup
   
    return relist, supportData


def aprioriGen(Lk, k):
    reList = []  
    lenLk = len(Lk)  
    
    for i in range(lenLk):
        for j in range(i + 1, lenLk):
            L1 = list(Lk[i])[:k - 2]
            L2 = list(Lk[j])[:k - 2]
            L1.sort()
            L2.sort()
            
            if L1 == L2:
                a = Lk[i] | Lk[j]  
                a1 = list(a) 
                b = []  
                for q in range(len(a1)):
                    t = [a1[q]]
                    tt = frozenset(set(a1) - set(t))
                    b.append(tt)

                
                t = 0
                for w in b:
                    
                    if w in Lk:
                        t += 1
                
                if len(b) == t:
                    reList.append(b[0] | b[1])

    return reList


def scanD(D, Ck, minSupport):
    
    sscnt = {}  
    for tid in D:  
        for can in Ck:  
            if can.issubset(tid):  
                if can not in sscnt:
                    sscnt[can] = 1
                else:
                    sscnt[can] += 1

    
    numItem = len(D)  
    reList = []  
    supportData = {}  
    for key in sscnt:
        support = sscnt[key] / numItem
        if support > minSupport:
            reList.insert(0, key)  
            supportData[key] = support
    return reList, supportData


def apriori(dataSet, minSupport=0.2):

    
    C1 = creatC1(dataSet)
    
    D = list(map(set, dataSet))
   
    L1, supportData = calSupport(D, C1, minSupport)
    L = [L1]  

    k = 2  
  
    while len(L[k - 2]) > 0:
        
        Ck = aprioriGen(L[k - 2], k)
       
        Lk, supK = scanD(D, Ck, minSupport)
       
        supportData.update(supK)
        
        L.append(Lk)  
        k += 1
    del L[-1]
   
    return L, supportData


def getSubset(fromList, totalList):

    for i in range(len(fromList)):
        t = [fromList[i]]
        tt = frozenset(set(fromList) - set(t))  

        if tt not in totalList:
            totalList.append(tt)
            tt = list(tt)
            if len(tt) > 1:
                getSubset(tt, totalList) 


def calcConf(freqSet, H, supportData, ruleList, minConf):


    for conseq in H:
        conf = supportData[freqSet] / supportData[freqSet - conseq]  

        
        lift = supportData[freqSet] / (supportData[conseq] * supportData[freqSet - conseq])
        if conf >= minConf and lift > 1:
            print(freqSet - conseq, '-->', conseq, '支持度', round(supportData[freqSet], 6), '置信度：', round(conf, 6),
                  'lift值为：', round(lift, 6))
            ruleList.append((freqSet - conseq, conseq, conf))


def get_rule(L, supportData, minConf=0.7):

    bigRuleList = []  
   
    for i in range(1, len(L)):
        for freqSet in L[i]:
            H1 = list(freqSet)
            all_subset = []  
            
            getSubset(H1, all_subset)
            
            calcConf(freqSet, all_subset, supportData, bigRuleList, minConf)
    return bigRuleList


if __name__ == '__main__':
    dataSet = loaddata()
   
    L, supportData = apriori(dataSet, minSupport=0.02)
    
    rule = get_rule(L, supportData, minConf=0.35)
